Common Lisp includes a complex and powerful
“declaration” mechanism that allows you to give the
compiler special hints about the types of data that will be
stored in particular variables, and about the ways those
variables and functions will be used. This package defines
versions of all the Common Lisp declaration forms:
declare, locally,
proclaim, declaim, and
the.
Most of the Common Lisp declarations are not currently useful in Emacs Lisp. For example, the byte-code system provides little opportunity to benefit from type information. A few declarations are meaningful when byte compiler optimizations are enabled, as they are by the default. Otherwise these declarations will effectively be ignored.
This function records a “global” declaration
specified by decl-spec. Since
cl-proclaim is a function, decl-spec
is evaluated and thus should normally be quoted.
This macro is like cl-proclaim, except that
it takes any number of decl-spec arguments, and
the arguments are unevaluated and unquoted. The
cl-declaim macro also puts (cl-eval-when
(compile load eval) …) around the declarations
so that they will be registered at compile-time as well as at
run-time. (This is vital, since normally the declarations are
meant to influence the way the compiler treats the rest of
the file that contains the cl-declaim form.)
This macro is used to make declarations within functions
and other code. Common Lisp allows declarations in various
locations, generally at the beginning of any of the many
“implicit progns” throughout Lisp
syntax, such as function bodies, let bodies,
etc. Currently the only declaration understood by
cl-declare is special.
In this package, cl-locally is no different
from progn.
cl-the returns the value of
form, first checking (if optimization settings
permit) that it is of type type. Future
byte-compiler optimizations may also make use of this
information to improve runtime efficiency.
For example, mapcar can map over both lists
and arrays. It is hard for the compiler to expand
mapcar into an in-line loop unless it knows
whether the sequence will be a list or an array ahead of
time. With (mapcar 'car (cl-the vector foo)), a
future compiler would have enough information to expand the
loop in-line. For now, Emacs Lisp will treat the above code
as exactly equivalent to (mapcar 'car foo).
Each decl-spec in a cl-proclaim,
cl-declaim, or cl-declare should be a
list beginning with a symbol that says what kind of declaration
it is. This package currently understands special,
inline, notinline,
optimize, and warn declarations. (The
warn declaration is an extension of standard Common
Lisp.) Other Common Lisp declarations, such as type
and ftype, are silently ignored.
specialSince all variables in Emacs Lisp are
“special” (in the Common Lisp sense),
special declarations are only advisory. They
simply tell the byte compiler that the specified variables
are intentionally being referred to without being bound in
the body of the function. The compiler normally emits
warnings for such references, since they could be
typographical errors for references to local variables.
The declaration (cl-declare (special var1
var2)) is equivalent to (defvar
var1) (defvar var2).
In top-level contexts, it is generally better to write
(defvar var) than (cl-declaim
(special var)), since defvar
makes your intentions clearer.
inlineThe inline decl-spec lists one or
more functions whose bodies should be expanded
“in-line” into calling functions whenever the
compiler is able to arrange for it. For example, the function
cl-acons is declared inline by this
package so that the form (cl-acons key
value alist) will expand
directly into (cons (cons key
value) alist) when it is called
in user functions, so as to save function calls.
The following declarations are all equivalent. Note that
the defsubst form is a convenient way to define
a function and declare it inline all at once.
(cl-declaim (inline foo bar)) (cl-eval-when (compile load eval) (cl-proclaim '(inline foo bar))) (defsubst foo (…) …) ; instead of defun
Please note: this declaration remains in effect after the containing source file is done. It is correct to use it to request that a function you have defined should be inlined, but it is impolite to use it to request inlining of an external function.
In Common Lisp, it is possible to use (declare
(inline …)) before a particular call to a
function to cause just that call to be inlined; the current
byte compilers provide no way to implement this, so
(cl-declare (inline …)) is currently
ignored by this package.
notinlineThe notinline declaration lists functions
which should not be inlined after all; it cancels a previous
inline declaration.
optimizeThis declaration controls how much optimization is performed by the compiler.
The word optimize is followed by any number
of lists like (speed 3) or (safety
2). Common Lisp defines several optimization
“qualities”; this package ignores all but
speed and safety. The value of a
quality should be an integer from 0 to 3, with 0 meaning
“unimportant” and 3 meaning “very
important”. The default level for both qualities is
1.
In this package, the speed quality is tied to
the byte-optimize flag, which is set to
nil for (speed 0) and to
t for higher settings; and the
safety quality is tied to the
byte-compile-delete-errors flag, which is set to
nil for (safety 3) and to
t for all lower settings. (The latter flag
controls whether the compiler is allowed to optimize out code
whose only side-effect could be to signal an error, e.g.,
rewriting (progn foo bar) to bar
when it is not known whether foo will be bound
at run-time.)
Note that even compiling with (safety 0), the
Emacs byte-code system provides sufficient checking to
prevent real harm from being done. For example, barring
serious bugs in Emacs itself, Emacs will not crash with a
segmentation fault just because of an error in a
fully-optimized Lisp program.
The optimize declaration is normally used in
a top-level cl-proclaim or
cl-declaim in a file; Common Lisp allows it to
be used with declare to set the level of
optimization locally for a given form, but this will not work
correctly with the current byte-compiler. (The
cl-declare will set the new optimization level,
but that level will not automatically be unset after the
enclosing form is done.)
warnThis declaration controls what sorts of warnings are
generated by the byte compiler. The word warn is
followed by any number of “warning qualities”,
similar in form to optimization qualities. The currently
supported warning types are redefine,
callargs, unresolved, and
free-vars; in the current system, a value of 0
will disable these warnings and any higher value will enable
them. See the documentation of the variable
byte-compile-warnings for more details.